use axum::{routing::{get, post}, Router};
use rust_decimal::Decimal;
use serde::Deserialize;

use crate::{error::AppErr, server::{res::Void, Cbor}, store::product::{self, TbProduct}};

#[derive(Debug, Deserialize)]
struct CreateProductReq {
    name: String,
    heat_time: u32,
    #[serde(with = "serde_bytes")]
    image: Box<[u8]>,
    expiration: u32,
    price: Decimal,
}

async fn on_create(req: Cbor<CreateProductReq>) -> Result<Cbor<u64>, AppErr> {
    let id = product::create(&req.name, req.heat_time, &req.image, req.expiration, req.price).await?;
    Ok(Cbor(id))
}

#[derive(Debug, Deserialize)]
struct UpdateProductReq {
    id: u64,
    name: String,
    heat_time: u32,
    #[serde(with = "serde_bytes")]
    image: Box<[u8]>,
    expiration: u32,
    price: Decimal,
}

async fn on_update(req: Cbor<UpdateProductReq>) -> Result<Void, AppErr> {
    product::update(req.id, &req.name, req.heat_time, &req.image, req.expiration, req.price).await?;
    Ok(Void)
}

async fn on_delete(id: Cbor<u64>) -> Result<Void, AppErr> {
    product::delete(id.0).await?;
    Ok(Void)
}

async fn on_query() -> Result<Cbor<Box<[TbProduct]>>, AppErr> {
    let ps = product::query_all().await?;
    Ok(Cbor(ps))
}

pub fn register() -> Router {
    Router::new()
        .route("/create", post(on_create))
        .route("/update", post(on_update))
        .route("/delete", post(on_delete))    
        .route("/query", get(on_query))
}




